package com.anjubao.parking.municipal.order.service;

import com.anjubao.parking.municipal.basezone.dto.DistrictsResDto;
import com.anjubao.parking.municipal.order.feign.BaseZoneClient;
import com.anjubao.parking.municipal.order.mapper.ParkingTradeOrderMapper;
import com.anjubao.parking.municipal.order.model.ParkingTradeOrder;
import com.anjubao.parking.municipal.payment.constant.ChargingTypeEnum;
import com.anjubao.parking.municipal.payment.constant.OrderStatusEnum;
import com.anjubao.parking.municipal.payment.constant.PayChannelIdEnum;
import com.anjubao.parking.municipal.payment.dto.DateFeeDto;
import com.anjubao.parking.municipal.payment.dto.OrderPayChannelFeeDto;
import com.anjubao.parking.municipal.payment.dto.OrderRecordTotalDto;
import com.anjubao.parking.municipal.payment.dto.OrderZoneFeeDto;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 订单统计
 *
 * @author zhuchunfeng
 */
@Service
public class ParkingStatOrderService {

    @Resource
    private ParkingTradeOrderMapper parkingTradeOrderMapper;
    @Autowired
    private BaseZoneClient baseZoneFeign;

    /**
     * 订单支付方式占比
     *
     * @param cityId    城市id
     * @param startTime 统计开始时间
     * @param endTime   统计结束时间
     * @return 订单支付方式占比
     */
    public List<OrderPayChannelFeeDto> queryParkingStatOrdersFee(Integer cityId, LocalDateTime startTime, LocalDateTime endTime) {
        //数据库查询数据
        List<OrderPayChannelFeeDto> channelFeeDtos = parkingTradeOrderMapper.queryParkingStatOrdersFee(cityId, startTime, endTime);
        //去除无关数据
        channelFeeDtos.removeIf(t -> !PayChannelIdEnum.exist(t.getPayChannelId()));
        //增加描述
        channelFeeDtos.forEach(t -> t.setPayChannelDesc(PayChannelIdEnum.getDescByCode(t.getPayChannelId())));
        //排序
        channelFeeDtos.sort(Comparator.comparingInt(OrderPayChannelFeeDto::getPayChannelId));
        return channelFeeDtos;
    }

    /**
     * * parking_trade_order  charging_type=4免费  charging_type in 1,2,3 and status=1收费停车  status=0欠费停车
     *
     * @param cityId    城市id
     * @param startTime 统计开始时间
     * @param endTime   统计结束时间
     * @return 停车记录总数
     */
    public OrderRecordTotalDto queryParkingTotal(Integer cityId, LocalDateTime startTime, LocalDateTime endTime) {
        //charging_type=4免费停车
        Integer freeParkingTotal = parkingTradeOrderMapper.selectCount(
                new QueryWrapper<>(new ParkingTradeOrder()
                        .setCityId(cityId)
                        .setChargingType(ChargingTypeEnum.FREE.getCode())
                ).lambda()
                        .ge(ParkingTradeOrder::getFulfillTime, startTime)
                        .lt(ParkingTradeOrder::getFulfillTime, endTime)
        );

        //charging_type in 1,2,3 and status=1收费停车
        Integer payParkingTotal = parkingTradeOrderMapper.selectCount(
                new QueryWrapper<>(new ParkingTradeOrder()
                        .setCityId(cityId)
                        .setStatus(OrderStatusEnum.PAID.getCode())
                ).lambda()
                        .ge(ParkingTradeOrder::getFulfillTime, startTime)
                        .lt(ParkingTradeOrder::getFulfillTime, endTime)
                        .in(ParkingTradeOrder::getChargingType, Arrays.asList(1, 2, 3))
        );

        //charging_type in 1,2,3 and status=0欠费停车
        Integer oweParkingTotal = parkingTradeOrderMapper.selectCount(
                new QueryWrapper<>(new ParkingTradeOrder()
                        .setCityId(cityId)
                        .setStatus(OrderStatusEnum.UN_PAID.getCode())
                ).lambda()
                        .ge(ParkingTradeOrder::getFulfillTime, startTime)
                        .lt(ParkingTradeOrder::getFulfillTime, endTime)
                        .in(ParkingTradeOrder::getChargingType, Arrays.asList(1, 2, 3)));

        OrderRecordTotalDto orderRecordTotalDto = new OrderRecordTotalDto();
        orderRecordTotalDto.setFreeParkingTotal(freeParkingTotal);
        orderRecordTotalDto.setArrearsParkingTotal(oweParkingTotal);
        orderRecordTotalDto.setPaidParkingTotal(payParkingTotal);
        orderRecordTotalDto.setParkingTotal(freeParkingTotal + oweParkingTotal + payParkingTotal);
        return orderRecordTotalDto;
    }

    /**
     * parking_trade_order status=1 按地区统计，where日期范围统计
     *
     * @param cityId    城市id
     * @param startTime 统计开始时间
     * @param endTime   统计结束时间
     * @return 按区域统计收费金额
     */
    public List<OrderZoneFeeDto> queryZonesPaidFee(Integer cityId, LocalDateTime startTime, LocalDateTime endTime, Integer status) {

        //查询数据
        List<OrderZoneFeeDto> orderZoneList = parkingTradeOrderMapper.queryZonesPaidFee(cityId, startTime, endTime, status);
        Map<Integer, OrderZoneFeeDto> districtIdMapOrderZone = orderZoneList.stream().collect(Collectors.toConcurrentMap(OrderZoneFeeDto::getDistrictId, Function.identity(), (k1, k2) -> k2));

        //所有的地区信息//TODO 通过feign调接口
        List<DistrictsResDto> result = baseZoneFeign.getDistricts(cityId).getResult();

        return result.stream()
                .map(districtsResDto -> {
                    OrderZoneFeeDto orderZoneFeeDto = districtIdMapOrderZone.get(districtsResDto.getDistrictId());
                    if (orderZoneFeeDto != null) {
                        return new OrderZoneFeeDto(districtsResDto.getDistrictId(), districtsResDto.getDistrictName(), orderZoneFeeDto.getDistrictTotalFee());
                    } else {
                        return new OrderZoneFeeDto(districtsResDto.getDistrictId(), districtsResDto.getDistrictName(), BigDecimal.ZERO);
                    }
                })
                .sorted((o1, o2) -> o2.getDistrictTotalFee().compareTo(o1.getDistrictTotalFee()))
                .collect(Collectors.toList());
    }

    public List<DateFeeDto> queryTotalFee(LocalDate startTime, LocalDate endTime) {
        String startFee = parkingTradeOrderMapper.queryTotalFee(startTime);
        String endFee = parkingTradeOrderMapper.queryTotalFee(endTime);
        List<DateFeeDto> res = Lists.newArrayList();
        res.add(new DateFeeDto().setDate(startTime.toString()).setFee(startFee));
        res.add(new DateFeeDto().setDate(endTime.toString()).setFee(endFee));
        return res;
    }
}

